Helpful Information
 
 
Category: C
C->malloc/free error.

Hi All,

The code has been fixed, with the help of this forum. For anyone wanting to see an easy way to implement classes in standard C89/C99 the code is posted at the end of this discussion


--
Happy Coding

Please post your code within the code tags (Hint: click on the # button when making a post, or enclose your code within [ code ] and [ /code ] tags (remove spaces in the above tags))

Your code isn't valid C or C++ and doesn't compile.

> It will again compile without warning but this time is segment faults on the assignment.
Because a cast is basically "STFU compiler, I know what I'm doing".
And a segfault is "No you don't, try again noob".

> Point* myPoint = (Point*) malloc(sizeof(Point*));
1. Don't cast malloc in C. You've already included stdlib so everything else is good. If you still feel the need to cast because of some error message, then ask what it means.
2. You're allocating the WRONG size (too little), so some of your assignments are trashing memory.
p = malloc ( sizeof *p );

You want to allocate the size of an object, not the size of a pointer to that object.

Oh, and I normally ignore code posted without code tags, I'm just feeling generous today.

Sorry i was using import instead of include which is compiler dependent and there were a silly mistakes.... below is an updated and stripped down version should show the problem.



#include <stdio.h>
#include <stdlib.h>

typedef struct {
int (*getX)();
void (*setX)(int x);
void (*die)();
} Point;

Point* NewPoint() {
//Put a new Point and x on the heap
Point* myPointer = (Point*) malloc(sizeof(Point));
int* myX = (int*) malloc(sizeof(int));

//Create some functions
//How do you put these functions on the heap?
//Are they automatically there? I'm confused
int getX() { return (int) myX; }
void setX(int x) { myX = (int*) x; }
void die() { free(myX); free(myPointer); }

//Assign the object its functions
myPointer->getX = getX;
myPointer->setX = setX;

//Return object
return myPointer;
}

int main() {
Point* test = NewPoint();

test->setX(5);
printf("Point.x equals %d" , test->getX());
//test->die();

return 0;
}

It still won't compile with my version of gcc (v4.0.1) on Mac. Mainly it is complaining about the declarations of functions int getX(), setX() and die() within NewPoint(). What compiler are you using

Incidentally, myX is local to NewPoint(), so when you return myX within getX(), it is currently working for you by pure luck only. Try calling some other functions between setX() and getX() and see if it still works. What you should do is make myX a member of Point and then set getX() and setX() to accept Point * as an argument (like this pointer in C++).

Hey there,

it is standard C code not C++ the compiler version output is gcc (Ubuntu 4.3.3-5ubuntu4) 4.3.3

I am compiling it with gcc -Wall -o test test.c and getting no warnings or errors.

You are the second out person to tell me that it wont compile and both are using GCC under Mac. Everyone else it works fine. Can you verify that your compiler allows nested functions. According the C89/C99 standards embedded functions have access to the containing functions variables.

Ok, I fixed it up for you. Some points to note:
1. I took out all your typecasts. Explicitly typecasting tells the compiler to shut up about warnings and this could sometimes hide errors in your code. In your case, it did. Your getX() routine happily converted an int* to an int and your setX() converted an int to an int* arbitrarily. Typecasting one type to another should be used very sparingly and only when you know what you're doing. This is why you weren't getting warnings, since you told the compiler to shut up by your typecasting.

2. Functions should be written as code. Function pointers, on the other hand, can be allocated on the heap. That is what I've done.

3. In C++, there is an invisible, implicit pointer to the object itself, called "this" which is automatically passed to all member functions of a class. So when you call obj->foo(5, 10), C++ actually calls foo(obj, 5, 10) when it compiles the code. Since this is C, we have to add this pointer ourselves and pass it ourselves as well. Hence, you'll see uses of test->getX(test) and test->setX(test, 5) and so on.


#include <stdio.h>
#include <stdlib.h>

typedef struct point {
int *myX;
int (*getX)(struct point *self);
void (*setX)(struct point *self, int x);
void (*die)(struct point *self);
} Point;

static int getX(Point *this)
{
return *(this->myX);
}

static void setX(Point *this, int x)
{
*(this->myX) = x;
}

static void die(Point *this)
{
free(this->myX);
free(this);
}

Point* NewPoint() {
//Put a new Point and x on the heap
Point* myPointer = (Point*) malloc(sizeof(Point));
if (!myPointer)
return NULL;

int* myX = malloc(sizeof(int));
if (!myX) {
free(myPointer);
return NULL;
}

myPointer->myX = myX;

//Assign the object its functions
myPointer->getX = getX;
myPointer->setX = setX;
myPointer->die = die;

//Return object
return myPointer;
}

int main() {
Point* test = NewPoint();

test->setX(test, 5);
printf("Point.x equals %d\n" , test->getX(test));
test->die(test);

return 0;
}


I will try out with my Ubuntu compiler at work tomorrow.

You Rock!

Thanks for all your help... and I looked up the problem with compiling on the mac for gcc. You need to add the flag -fnested-functions, they don't say why they broke norm just that they did.

OK this message is to finalize the post in case any one else was interested in creating Classes with object instances in C. Depending on which compiler you are using you may need to allow inner function with something like -fnested-functions other then that the below code uses no global methods or variables just one global struct for the class and one global initializer.



#include <stdio.h>
#include <stdlib.h>

typedef struct Point {
int (*getX)(struct Point* self);
void (*setX)(struct Point* self, int x);
void (*die)(struct Point* self);

struct {
int myX;
int myY;
} _private;
} Point;

Point* NewPoint() {
//Initialize Data Structure
Point* myPointer = (Point*) malloc(sizeof(Point));
if(!myPointer) return NULL;

//Create Member Functions
int getX(Point* this) { return this->_private.myX; }
void setX(Point* this, int x) { this->_private.myX = x; }
void die(Point* this){ free(this); }

//Assign the object its functions
myPointer->getX = getX;
myPointer->setX = setX;
myPointer->die = die;

//Return object
return myPointer;
}

int main() {
Point* test = NewPoint();

test->setX(test, 5);
printf("Point.x equals %d\n" , test->getX(test));
test->die(test);

return 0;
}










privacy (GDPR)